﻿using System;
using FunctionalCLR.Core;
using DhbInterfaces;
using DhbIterations;
using DhbFunctionEvaluation;

namespace FunctionalCLR.Shell.Function
{

    /// <summary>
    /// y = findroot(x*x-2*x, x, 0, 100);
    /// echo(x);
    /// echo(y);
    /// </summary>
    public class FindRootNode : ContextFuncNode
    {
        public FindRootNode()
            : base()
        {
            base.Value = "findroot";
        }

        public override object Evaluate()
        {
            if (Parameters.Count < 4)
            {
                throw new ArgumentException(
                    "useage: findroot(expr, param, min, max)");
            }

            int length = Parameters.Count;
            string expr = string.Empty;

            int start = Convert.ToInt32(
                Parameters[length-3].Evaluate());
            string param = Convert.ToString(
                Parameters[length - 2].Evaluate());
            Node exprNode = Parameters[length - 1];

            UnaryFunctionTranslator uft
            = new UnaryFunctionTranslator(
                this.Context.GetFunctionManager(), param);
            string fexpr = uft.Translate(exprNode);

            IOneVariableFunctionCompiler compiler =
                new IOneVariableFunctionCompiler();

            IOneVariableFunction func = compiler.Parse(fexpr);
            NewtonZeroFinder zeroFinder 
                = new NewtonZeroFinder(func, start);
            zeroFinder.DesiredPrecision 
                = DhbMath.DefaultNumericalPrecision;
            zeroFinder.Evaluate();

            Context.Assign(param, zeroFinder.Result);

            return zeroFinder.Result;
        }
    }
}
